# _*_coding:utf-8_*_

import time
from ATS.instrumentDriver import InstCom as inst
from ATS.datamanager.DataManager import DataManager
matrix = "MTRX1"
CMTR = "CMTR1"
DIO = "DIO1"


# import instrumentDriver.CVGeneralFunc.IVGeneralFunc_E4980A as CVFunc
def TestControler_AutoBegin(is_openall=1):
    """
    This function will be sent at Automation Begin.
    1. Get project ini setting.
    2. Initialize all instruments in system.
    """
    # {"ADMIN":{"Fail_Exit_Dev":1},"HANDLER":{"L":"BIN1", "C":"BIN2", "Pass":"BIN3"}}
    # __addglobal("Is_Stop", 0)
    proj_setting = DataManager().getCurIni()
    handler = proj_setting.get("HANDLER")
    # print "proj_setting",proj_setting
    if not handler:
        msg = "Please input the bin information under section [HANDLER] in project ini file. "
        return __err_handler(msg)
    fail_exit_dev = proj_setting.get("ADMIN", {}).get("fail_exit_dev", 1)
    __addglobal("Fail_Exit_Dev", fail_exit_dev)
    # print "****Fail_Exit_Dev",fail_exit_dev
    test_key = []
    for k in ["l", "c", "r", "pass"]:
        val = handler.get(k + "_bin", "")
        if val.startswith("BIN"):
            __addglobal(k.upper() + "_Bin", val)
            test_key.append(k.upper())
    __addglobal("Test_Key", test_key)
    # check use line in online.rcf
    # print "------------"
    dio = inst.getinstobj(DIO)
    # print dir(dio)
    lineconfig = dio.getlineconfig()
    # print "111111"
    use_line = lineconfig.get("use_line")
    # print "**************",use_line
    if not use_line:
        msg = "Please config digit IO line output information in online.rcf file."
        return __err_handler(msg)
    # print "&&&&&&&"
    dio_out = ["port%d/line%d" % (l / 10, l % 10) for l in use_line]
    rst_level = [0] * len(use_line)  # reset to low
    __addglobal("DIO_Out", dio_out)
    __addglobal("Rst_Level", rst_level)
    dio_counter = "ctr0"
    __addglobal("Counter", dio_counter)

    cmtr = inst.getinstobj(CMTR)
    if cmtr:
        cmtr.reset()
    if is_openall == 1:
        mtrx = inst.getinstobj(matrix)
        if mtrx:
            mtrx.DisconnectAll()

    counter_start = 0
    __addglobal("Last_Read", counter_start)
    dio.CreateTask("dout")
    dio.CreateDOChan(dio_out)
    dio.StartTask("dout")
    dio.WriteDigitalLines(rst_level)  # reset to high level

    dio.CreateTask("counter")
    dio.CreateCICountEdgesChan(dio_counter)
    dio.StartTask("counter")  # STart to monitor the handler

    __addglobal("eom_send", 0)


def TestControler_DevBegin():
    """
    This function will be sent at Device Begin.(one time handle loading device-package, \
    one or two real devices in single package.)
    1. Read value from counter.
        a. Waiting till the value is 1, represent device is loaded by handler.
        b. Check stop flag from global.
    2. Stop DIO task. THe counter will be reset to 0.
    3. Initialize bin value to pass.
    4. Initialize "skip device" to not skip.
    5. Initialize test result to pass
    """
    dio = inst.getinstobj(DIO)
    # Check if device is loaded.
    # is_stop = False #__getglobal("ATS_Stop_Flag") # read from global
    # is_gomanual = False #__getglobal("Continue_Flag")
    # posterror( "TestControler_DevBegin, read counter"+str(time.clock()))
    last_val = __getglobal("Last_Read")
    eom_send = __getglobal("eom_send")
    dio_out = __getglobal("DIO_Out")
    rst_level = __getglobal("Rst_Level")
    # print "Cur_Loop_Num", Cur_Loop_Num
    # num = Cur_Loop_Num
    num = 120000000
    if num % 100 == 1:
        print("Current loop", num)
    while True:
        is_stop = __getglobal("ATS_Stop_Flag")
        is_gomanual = __getglobal("Continue_Flag")
        if is_stop:
            return  # test end
        if is_gomanual:
            break  # skip counter read
        val = dio.ReadCounterScalarU32()
        # print "TestControler_DevBegin, read counter", time.clock()
        if val > last_val:
            # print "counter..",val
            counter_read = time.clock()
            __addglobal("counter_read", counter_read)
            if counter_read - eom_send > 0.03:
                pass
                # print(Cur_Loop_Num, "from EOM send to counter read, ", counter_read - eom_send)
            last_val = val
            break
        time.sleep(0.005)
    __addglobal("Last_Read", last_val)
    # dio.StopTask() # stop monitor
    # dio.ClearTask()#Clear then create dio out task when device end

    dio.WriteDigitalLines(rst_level)  # reset to high level

    bin_val = __getglobal("PASS_Bin")  # "BIN4"
    __addglobal("Bin_Val", bin_val)
    __addglobal("Exit_Dev", False)
    test_key = __getglobal("Test_Key")
    # test_key = ["L","C","R"]
    # note if same key tested for two devices,the value will be updated by the \
    # latest result.
    for k in test_key:
        key = k + "_PorF"
        __addglobal(key, 1)  # default to pass


def TestControler_TestEnd():
    """
    This function will be sent at Test End.
    1. If Bin value is pass. Get test result from global. Continue test if result pass. If fail, skip following \
    tests or not depends on user setting(GUI setup).
    2. Assign BIN if Fail.
    """
    pass_bin = __getglobal("PASS_Bin")
    bin_val = __getglobal("Bin_Val")
    is_gomanual = __getglobal("Continue_Flag")
    if is_gomanual:
        return
    if bin_val != pass_bin:  # failed in before tests. but device not skiped
        return
    test_key = __getglobal("Test_Key")
    for k in test_key:
        key = k + "_PorF"
        result = __getglobal(key)
        if result == 0:  # failed
            key = k + "_Bin"
            bin_val = __getglobal(key)
            __addglobal("Bin_Val", bin_val)  # assign bin
            is_exit_dev = __getglobal("Fail_Exit_Dev")
            # print "*** if fail,is_exit_dev ",is_exit_dev
            if is_exit_dev:
                __addglobal("Exit_Dev", True)  # is exit current device
            #                print "**** Exit_Dev", True
            break
    return


def TestControler_DevEnd():
    """
    This function will be sent at Device end.
    1. Send bin val to DIO
    2. 2014-04-23: Check "NOT_END" flag from platform, if True, to force handler timeout,
        don't send EOM. Automation will conntinue to Dev_Begin to wait start signal or
        end_lot flag. Operator will restart handler if needed.
    """
    dio_out = __getglobal("DIO_Out")
    bin_val = __getglobal("Bin_Val")  # BIN4
    is_gomanual = __getglobal("Continue_Flag")
    if is_gomanual:  # reset continue flag
        __addglobal("Continue_Flag", False)
        return

    # registerBinResult(Cur_Dev, Cur_Loop_Num, bin_val)

    dio = inst.getinstobj(DIO)
    line_config = dio.getlineconfig()
    # line_config={1:"BIN1",2:"BIN2", 3:"EOM", "use_line":[1,2,3,4]}
    bin_assign_val = []
    eom_val = []
    eom_end_val = []
    for l_ind in line_config["use_line"]:
        bin = line_config[l_ind]  # "BIN1"
        if bin == "EOM":
            eom_val.append(1)
            eom_end_val.append(0)  # shape EOM as a Pulse
            bin_assign_val.append(0)  # EOM sent after bin assign
        elif bin == bin_val:
            bin_assign_val.append(1)
            eom_val.append(1)  # keep bin value at high when EOM sent
            eom_end_val.append(1)
        else:  # not BIN or EOM, keep high
            bin_assign_val.append(0)
            eom_val.append(0)
            eom_end_val.append(0)
    # print "TestControler_DevEnd, time before send bin", time.clock()

    counter_read = __getglobal("counter_read")
    bin_assign = time.clock()
    if bin_assign - counter_read > 0.2:
        pass
        # print(Cur_Loop_Num, "From counter read to bin assign,", bin_assign - counter_read)
    dio.WriteDigitalLines(bin_assign_val)
    # print "TestControler_DevEnd, time after send bin", time.clock()
    if not __getglobal("NOT_END"):
        dio.WriteDigitalLines(eom_val)
        # posterror( "TestControler_DevEnd, time before eom"+ str(time.clock()))
        time.sleep(0.02)
        eom_send = time.clock()
        dio.WriteDigitalLines(eom_end_val)
        __addglobal("eom_send", eom_send)
    else:  # reset to default
        __addglobal("NOT_END", False)


def __addglobal(k, val):
    # print "addgdata" ,k,val
    # addgdata(k, val)
    pass

def __getglobal(k):
    # gdata = {"Is_Stop":1, "Fail_Exit_Dev":1, "Exit_Dev":False, "Test_Key": ["Cp", "Rs"], "Bin_Val":"BIN4", "Pass_Bin":"BIN4", "Cp_Bin":"BIN1"}
    # print "__getglobal, k",k
    val = eval(k)
    # val = getgdata(k)
    # # print "__getglobal, val",val
    return val
    pass


def __err_handler(msg):
    # posterror(msg)
    __addglobal("Test_Abort", True)
    return
